package com.med.service.impl;

import com.med.dto.RespondDTO;
import com.med.entity.AppointmentDO;
import com.med.entity.AppointmentOrderDO;
import com.med.entity.DoctorDO;
import com.med.entity.MedicineOrderDO;
import com.med.mapper.OrderFrontMapper;
import com.med.service.IOrderFrontService;
import com.med.vo.OrderVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @BelongsProject: internet-based-healthcare02
 * @BelongsPackage: com.med.service.impl
 * @Author: WWJ
 * @CreateTime: 2025-08-27 15:51
 * @Description: 订单前台服务实现（适配若依框架Redis，存储医生预约信息）
 * @Version: 1.0
 */
@Service
public class OrderFrontService implements IOrderFrontService {
    @Autowired
    private OrderFrontMapper orderFrontMapper;

    /**
     * 注入若依框架默认的RedisTemplate<Object, Object>
     * （若依框架RedisConfig默认定义此类型Bean，避免注入冲突）
     */
    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;

    // Redis键前缀：统一标识医生预约业务，避免与其他Redis数据冲突
    private static final String APPOINTMENT_PREFIX = "appointment:schedule:";
    // 时间格式化器：将Timestamp转为无分隔符字符串（如20250828140000），用于构建Redis键
    // 注意：SimpleDateFormat非线程安全，此处作为成员变量需确保单线程使用（遍历逻辑为单线程）
    private static final SimpleDateFormat TIME_FORMATTER = new SimpleDateFormat("yyyyMMddHHmmss");
    // （可选）Redis数据过期时间：若后续需清理历史数据，可设置7天过期（单位：天）
    private static final long EXPIRE_DAYS = 1;


    @Override
    public List<AppointmentOrderDO> selectAllOrder(Integer userId) {
        // 原逻辑不变：查询用户所有预约订单
        List<AppointmentOrderDO> dos = orderFrontMapper.selectAllOrder(userId);
        return dos;
    }

    @Override
    public List<MedicineOrderDO> queryMedicineOrder(Integer userId) {
        // 原逻辑不变：查询用户所有药品订单
        List<MedicineOrderDO> list = orderFrontMapper.queryMedicineOrder(userId);
        return list;
    }

    @Override
    public List<AppointmentDO> getAllAppointment() {
        // 1. 从数据库查询所有医生的可预约时段（含docId和appointmentTime）
        List<AppointmentDO> appointmentList = orderFrontMapper.getAllAppointment();

        // 2. 遍历数据，逐个存入Redis
        for (AppointmentDO appointment : appointmentList) {
            // 跳过无效数据：医生ID或预约时间为空时不处理，避免空指针异常
            if (appointment.getDocId() == null || appointment.getAppointmentTime() == null) {
                continue;
            }

            try {
                // 3. 处理时间格式：将Timestamp转为字符串，用于构建Redis键
                Timestamp appointmentTime = appointment.getAppointmentTime();
                String timeStr = TIME_FORMATTER.format(appointmentTime); // 结果示例：20250828140000

                // 4. 构建Redis唯一键：格式=前缀+医生ID+格式化时间
                // 示例：appointment:schedule:5:20250828140000（医生ID=5，时间=2025-08-28 14:00:00）
                Object redisKey = APPOINTMENT_PREFIX + appointment.getDocId() + ":" + timeStr;

                // 5. 避免重复存储：仅当键不存在时才存入Redis（防止覆盖已有的预约状态）
                if (!redisTemplate.hasKey(redisKey)) {
                    // 存入Redis：键=上述构建的key，值=完整的AppointmentDO对象（若依Redis会自动序列化）
                    redisTemplate.opsForValue().set(redisKey, appointment);

                    // （可选）设置过期时间：7天后自动清理，避免Redis数据膨胀
                    redisTemplate.expire(redisKey, EXPIRE_DAYS, TimeUnit.DAYS);

                    // （可选）日志打印：便于调试，确认存储结果
                    System.out.printf("Redis存储成功：键=%s，医生ID=%d，预约时间=%s%n",
                            redisKey, appointment.getDocId(), appointmentTime);
                }
            } catch (Exception e) {
                // 异常处理：避免单条数据处理失败导致整个循环中断
                System.err.printf("Redis存储失败：医生ID=%d，预约时间=%s，错误信息=%s%n",
                        appointment.getDocId(), appointment.getAppointmentTime(), e.getMessage());
            }
        }

        // 6. 返回数据库原始数据，不影响原有业务逻辑
        return appointmentList;
    }

    /**
     * @Description: 我的药方
     * @Param:
     * @return:
     */
    @Override
    public RespondDTO queryMedicine(OrderVO orderVO) {
        List<MedicineOrderDO> queryMedicine = orderFrontMapper.queryMedicine(orderVO);

        if (queryMedicine != null) {
            return RespondDTO.success(queryMedicine);
        }
        return null;
    }

    /**
     * @Description: 查看医生信息
     * @Param:
     * @return:
     */
    @Override
    public RespondDTO doctorInfo(OrderVO orderVO) {
        DoctorDO doctorInfo = orderFrontMapper.doctorInfo(orderVO);
        if (doctorInfo != null) {
            return RespondDTO.success(doctorInfo);
        }
        return null;
    }

    @Override
    public RespondDTO insertComment(OrderVO orderVO) {
        Integer insertComment = orderFrontMapper.insertComment(orderVO);
        if (insertComment != null) {
            return RespondDTO.success(insertComment);
        }
        return null;
    }

    /**
    * @Description: 判断评论是否存在
    * @Param:
    * @return:
    */
    @Override
    public RespondDTO isComment(OrderVO orderVO) {
        Boolean comment = orderFrontMapper.isComment(orderVO);
        if (comment != null) {
            return RespondDTO.success(comment);
        }
        return null;
    }


    /**
     * （可选）辅助方法：根据医生ID和时间查询Redis中的预约信息
     * @param docId 医生ID
     * @param appointmentTime 预约时间（Timestamp类型）
     * @return AppointmentDO 预约信息（null表示未找到）
     */
    public AppointmentDO getAppointmentFromRedis(Long docId, Timestamp appointmentTime) {
        try {
            String timeStr = TIME_FORMATTER.format(appointmentTime);
            Object redisKey = APPOINTMENT_PREFIX + docId + ":" + timeStr;
            return (AppointmentDO) redisTemplate.opsForValue().get(redisKey);
        } catch (Exception e) {
            System.err.printf("Redis查询失败：医生ID=%d，预约时间=%s，错误信息=%s%n",
                    docId, appointmentTime, e.getMessage());
            return null;
        }
    }


    /**
     * （可选）辅助方法：删除Redis中的预约信息（用于数据清理或取消预约）
     * @param docId 医生ID
     * @param appointmentTime 预约时间（Timestamp类型）
     * @return boolean 删除结果（true=成功，false=失败或键不存在）
     */
    public boolean deleteAppointmentFromRedis(Long docId, Timestamp appointmentTime) {
        try {
            String timeStr = TIME_FORMATTER.format(appointmentTime);
            Object redisKey = APPOINTMENT_PREFIX + docId + ":" + timeStr;
            return redisTemplate.delete(redisKey);
        } catch (Exception e) {
            System.err.printf("Redis删除失败：医生ID=%d，预约时间=%s，错误信息=%s%n",
                    docId, appointmentTime, e.getMessage());
            return false;
        }
    }
}